BSP2 for Engine Coders
--------------------------------------------------------------------------------------------------------------

The objective of BSP2 is to address some limits in the stock BSP29 format.  While many engines have boosted
limits, there remain some cases where the on-disk format enforces a hard limit of 64k.  During the course of RMQ
development these cases were hit on a number of occasions; it was clear that we were exceeding the capabilities
of the Quake formats and that a more robust and general solution was needed.

Alternatives such as Half-Life BSP, Quake II BSP, Quake III BSP or others were considered but rejected on grounds
of legal issues, not actually doing anything to fix this problem, enforcing too many changes in the content
creation pipeline (such as changing your map editor) and enforcing too many (and too complex) changes in engine
code.

BSP2 will coexist peacefully with BSP29 so far as is possible; minimal changes are required to engine code (the
largest by far being in the loader), the .map format remains exactly the same, and - while new map compiling tools
are needed - the changes to these tools are also extremely minimal and can be made in the order of 30 minutes or
so per tool.

BSP2 is not a radical revision of the format.  You won't find RGB lightmaps, detail brushes, 32-bit textures
or any such major overhaul here.  These are left for other already standardised ways of providing such
content.  It's sole objective is to overcome limits that prevent content creators from fully realising their
visions.  By choosing this approach it is hoped that the path to implementing  BSP2 support in as many engines
who's authors choose to do so is as eased as is possible, and dependencies on other features (such as RGB
lightmaps) are not an obstacle.

--------------------------------------------------------------------------------------------------------------

This document outlines the requirements for implementing RMQ BSP2 support in your engine.  Because all engine
codebases are different I am not going to provide a set of copy-and-paste code but instead will give a fairly
high-level overview of the changes required.  The exception is where I give the new on-disk structs for BSP2
in full.

The basic steps are:

- Change the in-memory formats for certain BSP structs.
- Detect the version.
- Implement the loaders.


Changing the in-memory formats
--------------------------------------------------------------------------------------------------------------

This is a simple matter of switching the in-memory formats from using short (or unsigned short) to int (or
unsigned int) as appropriate.  It is non-destructive, will enable you to use the very same in-memory formats
for both BSP29 and BSP2, and can be done even if you don't intend to implement BSP2 (or don't intend to implement
it yet).  Memory usage will go up a little, but this should not be a problem unless you still need to run on an
8 MB machine.

In general, an on-disk struct name is prefixed by "d" and an in-memory struct name is prefixed by "m" (there
are some few exceptions) - see bspfile.h and model.h/gl_model.h for further info.

You will need to implement your own mclipnode_t struct as stock ID Quake uses dclipnode_t for both on-disk and
in-memory.  See FitzQuake 0.85 for an example of this.

One side-effect of this is that some ASM code in world.c will need to be switched to the equivalent C function;
this should not cause a noticeable performance hit for most people.


Detecting the version
--------------------------------------------------------------------------------------------------------------

The BSP2 version is defined as (('B' << 24) | ('S' << 16) | ('P' << 8) | '2') using the same endianness
convention as stock BSP29.

Once we have identified this we are almost ready to load the file, but first we must define some new structs in
bspfile.h (Note that the use of "29a" in the struct names is a historical artefact from an earlier working title
for the format.  If you are building a map compiling tool you will also need to add dmarksurfaces29a as an 
unsigned int.):

typedef struct
{
	int			planenum;
	int			children[2];	// negative numbers are -(leafs+1), not nodes
	short		mins[3];		// for sphere culling
	short		maxs[3];
	unsigned int	firstface;
	unsigned int	numfaces;	// counting both sides
} dnode29a_t;

typedef struct
{
	int			planenum;
	int			children[2];	// negative numbers are contents
} dclipnode29a_t;

typedef struct
{
	unsigned int	v[2];		// vertex numbers
} dedge29a_t;

typedef struct
{
	int			planenum;
	int			side;

	int			firstedge;		// we must support > 64k edges
	int			numedges;
	int			texinfo;

	// lighting info
	byte		styles[MAXLIGHTMAPS];
	int			lightofs;		// start of [numstyles*surfsize] samples
} dface29a_t;

typedef struct
{
	int			contents;
	int			visofs;				// -1 = no visibility info

	short		mins[3];			// for frustum culling
	short		maxs[3];

	unsigned int		firstmarksurface;
	unsigned int		nummarksurfaces;

	byte		ambient_level[NUM_AMBIENTS];
} dleaf29a_t;


Implementing the Loaders
--------------------------------------------------------------------------------------------------------------

From here the only major remaining change is to implement new versions of certain brushmodel loading functions
to support BSP2.  The functions that need new versions are:

- Mod_LoadEdges
- Mod_LoadFaces
- Mod_LoadNodes
- Mod_LoadLeafs
- Mod_LoadClipnodes
- Mod_LoadMarksurfaces

For each of these functions the "in" pointer changes to the new version of the struct, and anything that was
previously loaded as a "LittleShort" is now loaded as a "LittleLong".  In some cases the loading function may
be significantly simpler than the older one as you will not need to cast to unsigned short and nor will you
need to implement any workaround for counts above 32k.

You may find it easier and cleaner to split some functions into two or even three separate parts, with
different parts being common for both versions, dedicated to BSP29 or dedicated to BSP2.  This is almost
certainly the case with Mod_LoadFaces.


License
--------------------------------------------------------------------------------------------------------------

This program is free software; you can redistribute it and/or modify it under 
the terms of the GNU General Public License as published by the Free Software 
Foundation; either version 3 of the License, or (at your option) any later 
version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY 
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with 
this program; if not, write to the Free Software Foundation, Inc., 59 Temple 
Place - Suite 330, Boston, MA  02111-1307, USA.

